<template>
	<canvas
		id="canvas"
		ref="canvas"
		:width="width"
		:height="height"
		@click="updateCanvas"
	></canvas>
</template>
<script>
export default {
	data() {
		return {
			ctx: null,
			computedWidth: 0,
			computedHeight: 0,
		};
	},
	props: {
		value: {
			type: String,
			default: "",
		},
		nums: {
			type: Number,
			default: 4,
		},
		width: {
			type: Number,
			default: 300,
		},
		height: {
			type: Number,
			default: 80,
		},
		color: String,
		fillStyle: {
			type: String,
			default: "#fff",
		},
		randomLine: {
			type: Boolean,
			default: false,
		},
		clickUpdate: {
			type: Boolean,
			default: true,
		},
	},
	mounted() {
		const ramdomStr = this.getRandomStr();
		this.initCanvas();
		this.setCanvas(ramdomStr);
	},
	methods: {
		initCanvas() {
			const canvas = this.$refs.canvas;

			const ctx = canvas.getContext("2d");

			const computedStyle = getComputedStyle(canvas);

			this.ctx = ctx;

			this.computedWidth = parseFloat(computedStyle.width);

			this.computedHeight = parseFloat(computedStyle.height);

			ctx.fillStyle = this.fillStyle;

			ctx.fillRect(0, 0, this.computedWidth, this.computedHeight);

			this.randomLine && this.setRandomLine(ctx);
		},

		getRandomStr() {
			const _str =
				"abcdefghijkmlnopQrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

			let randomStr = "";
			if (!this.value) {
				for (var i = 0; i < this.nums; i++) {
					randomStr += _str[Math.floor(Math.random() * _str.length)];
				}
			} else {
				randomStr = this.value;
			}

			this.$emit("getImgCode", randomStr);

			return randomStr;
		},

		setRandomLine(ctx) {
			const computedWidth = this.computedWidth;
			const computedHeight = this.computedHeight;
			const nums = this.nums;
			const lineNums = Math.floor(computedWidth / nums);

			for (let i = 0; i < lineNums; i++) {
				ctx.save();

				ctx.beginPath();

				ctx.strokeStyle = this.getRandomRgb();

				ctx.translate(
					10 + i * (computedWidth / lineNums),
					Math.random() * computedHeight
				);

				ctx.rotate(this.getRandomDeg());

				ctx.moveTo(0, 0);

				ctx.lineTo(0, Math.random() * computedHeight);

				ctx.stroke();

				ctx.restore();
			}
		},

		setCanvas(str) {
			const len = str.length;
			const ctx = this.ctx;
			const fontsize = this.setFont();
			const computedHeight = this.computedHeight;
			const computedWidth = this.computedWidth;

			ctx.font = `${fontsize}px sans-serif`;

			ctx.save();

			for (let i = 0; i < len; i++) {
				const scaleBase = Math.random() > 0.5 ? 1.1 : 0.9;

				const randomRgb = this.getRandomRgb();

				ctx.fillStyle = this.color ?? randomRgb;

				ctx.translate(
					(computedWidth - fontsize * 4) / len + fontsize * i,
					parseFloat(computedHeight) / 2
				);

				ctx.rotate(this.getRandomDeg());

				ctx.scale(scaleBase, scaleBase);

				ctx.textBaseline = "middle";

				ctx.fillText(str[i], 0, 0);

				ctx.restore();

				ctx.save();
			}
		},

		updateCanvas() {
			if (!this.clickUpdate) return;

			const ctx = this.ctx;

			const ramdomStr = this.getRandomStr();

			ctx.clearRect(0, 0, this.computedWidth, this.computedHeight);

			this.initCanvas();

			this.setCanvas(ramdomStr);
		},

		getRandomDeg() {
			return (Math.PI / 180) * (-45 + Math.random() * 90);
		},

		getRandomRgb() {
			return `rgb(${Math.floor(Math.random() * 255)},${Math.floor(
				Math.random() * 255
			)},${Math.floor(Math.random() * 255)})`;
		},

		setFont() {
			let fontsize = this.computedWidth / (this.nums * 1.1);

			if (fontsize >= this.computedHeight) {
				fontsize = this.computedHeight * 0.8;
			}

			return fontsize;
		},
	},
};
</script>
